﻿using GMS.NET.SqlSugarCore.DbCore;
using MiniExcelLibs;
using MiniExcelLibs.OpenXml;
using System.Reflection;
using System.Text;

namespace GMS.NET.Application.Service.System.Tools.Manger
{
    [AllowAnonymous]
    [DynamicApiController]
    public class DatabaseService : DbManger, IDatabaseService
    {
        /// <summary>
        /// 根据命名空间获取实体并创建数据库表
        /// </summary>
        /// <param name="Param"></param>
        /// <returns></returns>
        public void CreateEntitysToDatabaseTable([FromBody] string nameSpace)
        {
            var allTypes = App.EffectiveTypes;
            // 获取属于目标命名空间的实体类Type
            var entityTypes = allTypes.Where(t => t.Namespace == nameSpace && t.IsClass);
            foreach (var entityType in entityTypes)
            {
                if (entityType.IsDefined(typeof(SplitTableAttribute)))
                    MasterDb.CodeFirst.SplitTables().InitTables(entityType);
                else
                    MasterDb.CodeFirst.InitTables(entityType);
            }
        }
        /// <summary>
        /// 根据excel创建excel实体和数据库表
        /// </summary>
        /// <param name="excel"></param>
        public async Task CreateExcelToEntitysFileAndDbTable([FromQuery] string nameSpace)
        {
            var EntityUrl = App.Configuration.GetSection("EntityFileDir").Value;
            using (var memoryStream = new MemoryStream())
            {
                await App.HttpContext.Request.Body.CopyToAsync(memoryStream);
                var sheets = memoryStream.GetSheetNames();
                foreach (var sheet in sheets)
                {
                    var IsSplit = sheet.Split('-')[2]=="split";
                    var TableName = sheet.Split('-')[1];
                    var EntityName = sheet.Split('-')[0];
                    var EntityFileUrl = $"{EntityUrl}{EntityName}.txt";
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine($"namespace {nameSpace}");
                    sb.AppendLine("{");
                    sb.AppendLine("\t///<summary>");
                    sb.AppendLine($"\t///{TableName}");
                    sb.AppendLine("\t///</summary>");
                    if(IsSplit)  sb.AppendLine("\t[SplitTable(SplitType.Year)]");
                    if (IsSplit) sb.AppendLine($"\t[SugarTable(\"{EntityName}_{{year}}{{month}}{{day}}\")]");
                    sb.AppendLine($"\tpublic partial class {EntityName}");
                    sb.AppendLine("\t{");
                    sb.AppendLine("\t\t/// <summary>");
                    sb.AppendLine("\t\t///");
                    sb.AppendLine("\t\t/// </summary>");
                    sb.AppendLine("\t\tpublic void SetAddUser()");
                    sb.AppendLine("\t\t{");
                    sb.AppendLine("\t\t\tthis.Creator = UserInfo.UserId;");
                    sb.AppendLine("\t\t\tthis.Modifier = UserInfo.UserId;");
                    sb.AppendLine("\t\t\tthis.Creationtime = DateTime.Now;");
                    sb.AppendLine("\t\t\tthis.Modifytime = DateTime.Now;");
                    sb.AppendLine("\t\t}");
                    sb.AppendLine("");
                    sb.AppendLine("\t\t/// <summary>");
                    sb.AppendLine("\t\t///");
                    sb.AppendLine("\t\t/// </summary>");
                    sb.AppendLine("\t\tpublic void SetUpdateUser()");
                    sb.AppendLine("\t\t{");
                    sb.AppendLine("\t\t\tthis.Modifier = UserInfo.UserId;");
                    sb.AppendLine("\t\t\tthis.Modifytime = DateTime.Now;");
                    sb.AppendLine("\t\t}");
                    sb.AppendLine("");
                    sb.AppendLine("\t\t/// <summary>");
                    sb.AppendLine("\t\t///");
                    sb.AppendLine("\t\t/// </summary>");
                    sb.AppendLine($"\t\tpublic {EntityName}() {{ }}");
                    sb.AppendLine("");
                    sb.AppendLine("\t\t/// <summary>");
                    sb.AppendLine("\t\t/// Desc:Guid");
                    sb.AppendLine("\t\t/// </summary>");
                    sb.AppendLine("\t\t[SugarColumn(IsPrimaryKey = true)]");
                    sb.AppendLine("\t\tpublic Guid Id { get; set; }");
                    sb.AppendLine("");
                    var dataList = (await memoryStream.QueryAsync<DatabaseTemplate>(sheetName: sheet)).ToList();
                    foreach (var data in dataList)
                    {
                        sb.AppendLine("\t\t/// <summary>");
                        sb.AppendLine($"\t\t/// Desc:{data.Descr}");
                        sb.AppendLine("\t\t/// </summary>");
                        if (data.Type!.Contains("string"))
                        {
                            var Length= Convert.ToInt32(data.Type.Split("-")[1]);
                            sb.AppendLine($"\t\t[SugarColumn({(data.IsNull=="Y"? "IsNullable = true":"")}{(Length>0 && data.IsNull == "Y" ? ",Length = 100" : Length > 0? "Length = 100":"")})]");
                            sb.AppendLine($"\t\tpublic string? {data.Name} {{ get; set; }}");
                        }
                        else if (data.Type.Contains("int"))
                        {
                            if (data.IsNull == "Y") sb.AppendLine("\t\t[SugarColumn(IsNullable = true)]");
                            sb.AppendLine($"\t\tpublic int {data.Name} {{ get; set; }}");
                        }
                        else if (data.Type.Contains("decimal"))
                        {
                            if (data.IsNull == "Y") sb.AppendLine("\t\t[SugarColumn(IsNullable = true)]");
                            sb.AppendLine($"\t\tpublic decimal {data.Name} {{ get; set; }}");
                        }
                        else if (data.Type.Contains("datetime"))
                        {
                            if (data.IsNull == "Y") sb.AppendLine("\t\t[SugarColumn(IsNullable = true)]");
                            sb.AppendLine($"\t\tpublic DateTime{(data.IsNull == "Y"?"?":"")} {data.Name} {{ get; set; }}");
                        }
                        else
                        {
                            if (data.IsNull == "Y") sb.AppendLine("\t\t[SugarColumn(IsNullable = true)]");
                            sb.AppendLine($"\t\tpublic string? {data.Name} {{ get; set; }}");
                        }
                        sb.AppendLine("");
                    }
                    sb.AppendLine("\t\t/// <summary>");
                    sb.AppendLine("\t\t/// Desc:创建时间");
                    sb.AppendLine("\t\t/// </summary>");
                    if (IsSplit) sb.AppendLine("\t\t[SplitField]");
                    sb.AppendLine("\t\tpublic DateTime Creationtime { get; set; }");
                    sb.AppendLine("");
                    sb.AppendLine("\t\t/// <summary>");
                    sb.AppendLine("\t\t/// Desc:创建人");
                    sb.AppendLine("\t\t/// </summary>");
                    sb.AppendLine("\t\t[SugarColumn(Length = 100)]");
                    sb.AppendLine("\t\tpublic string? Creator { get; set; }");
                    sb.AppendLine("");
                    sb.AppendLine("\t\t/// <summary>");
                    sb.AppendLine("\t\t/// Desc:修改时间");
                    sb.AppendLine("\t\t/// </summary>");
                    sb.AppendLine("\t\tpublic DateTime Modifytime { get; set; }");
                    sb.AppendLine("");
                    sb.AppendLine("\t\t/// <summary>");
                    sb.AppendLine("\t\t/// Desc:修改人");
                    sb.AppendLine("\t\t/// </summary>");
                    sb.AppendLine("\t\t[SugarColumn(Length = 100)]");
                    sb.AppendLine("\t\tpublic string? Modifier { get; set; }");
                    sb.AppendLine("");
                    sb.AppendLine("\t}");
                    sb.AppendLine("}");
                    File.WriteAllText(EntityFileUrl, sb.ToString());
                    string newFilePath = Path.ChangeExtension(EntityFileUrl, ".cs");
                    File.Move(EntityFileUrl, newFilePath,true);
                }
            }
        }
        /// <summary>
        /// 获取excel创表数据库模板文件流
        /// </summary>
        /// <param name="Param"></param>
        /// <returns></returns>
        [NonUnify]
        public async Task<MemoryStream> DatabaseExcelTempStream()
        {
            var values = new List<Dictionary<string, object>>()
                        {
                            new Dictionary<string, object>(){
                                 { "序号", "1" },
                                 { "名称", "Test" },
                                 { "描述", "测试字段" },
                                 { "类型", "string-10" },
                                 { "关键字", "" },
                                 { "允许为空", "N" },
                                 { "例", "测试" }
                            }
                        };

            var Stream = await MiniExcelTool.GetExcelStreamAsync(values, "TestTable-测试表格-split");
            return Stream;
        }
    }
}
